﻿using System;

namespace Samurai.Wakizashi.Workflow
{
    public class DelegatedWorkflowStep<T> : WorkflowStepBase<T> where T : class, IWorkflowContext 
    {
        private readonly Action<T> _action;
        private readonly Action _parameterlessAction;
        private readonly string _stepName;

        #region Constructors

        /// <summary>
        /// Initializes a new instance of the <see cref="DelegatedWorkflowStep&lt;T&gt;"/> class.
        /// </summary>
        /// <param name="action">The action.</param>
        /// <param name="stepName">Name of the step.</param>
        public DelegatedWorkflowStep(Action<T> action, string stepName)
        {
            if (action == null) throw new ArgumentNullException("action");
            _action = action;

            if (!string.IsNullOrEmpty(stepName))
                _stepName = stepName;
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="DelegatedWorkflowStep&lt;T&gt;"/> class.
        /// </summary>
        /// <param name="action">The action.</param>
        /// <param name="stepName">Name of the step.</param>
        public DelegatedWorkflowStep(Action action, string stepName)
        {
            if (action == null) throw new ArgumentNullException("action");
            _parameterlessAction = action;

            if (!string.IsNullOrEmpty(stepName))
                _stepName = stepName;
        }

        #endregion

        #region Overrides of WorkflowStepBase<T>

        /// <summary>
        /// Gets the name of the step.
        /// </summary>
        /// <value>The name of the step.</value>
        public override string StepName
        {
            get
            {
                if (!string.IsNullOrEmpty(_stepName)) return _stepName;
                if (_action != null) return _action.Method.Name;
                if (_parameterlessAction != null) return _parameterlessAction.Method.Name;

                return GetType().Name;
            }
        }

        /// <summary>
        /// Executes the step.
        /// </summary>
        public override void ExecuteStep()
        {
            try
            {
                if(_parameterlessAction != null)
                    _parameterlessAction.Invoke();
                else
                    _action.Invoke(Context);

                NotifyStepCompleted();
            }
            catch (Exception e)
            {
                NotifyStepFailed(e);
            }
        }

        #endregion
    }
}
